/**********************************************************************
 * File:        arab_classes.cpp
 * Description: This file groups all the classes inhereted from Tesseract's classes that
 *				need more attributes to be able to store Arabic text features and properties.
 * Author:      Fuad Jamour
 * Created:     Tue Mar 10 2009
 **********************************************************************/

#ifndef		ARAB_CLASSES_H
#define		ARAB_CLASSES_H

#include	"img.h"
#include	"img_macros.h"
#include	"blobbox.h"
#include	"elst2.h"
#include	"imgs.h"
#include	"arab_structs.h"

/**********************************************************************
 * ARAB_IMAGE
 *
 * This class contains all the functions related to the analysis of the Arabic word and the information
 * needed for analyzing it.
 **********************************************************************/
class ARAB_IMAGE:public IMAGE
{
public:
	ARAB_IMAGE():IMAGE(){	//Constructor
		connCmpPtr_BeforeSeg = NULL;
		connCmpPtr_AfterSeg = NULL;
		subwordsPtr = NULL;
		charactersPtr = NULL;
		inc_x1_codes = NULL;
		dec_x2_codes = NULL;
		inc_x1_codes_Segmented = NULL;
		dec_x2_codes_Segmented = NULL;
		numOfCmps_BeforeSeg = 0;
		numOfCmps_AfterSeg = 0;
		numOfSubwords = 0;
		numOfCharacters = 0;
		numOfCmps_Final = 0;
		numOfChars_Final = 0;

		thinned = NULL;
		thinnedGreyLevel = !this->get_white_level();

		BaseLine = -1;
	}

	~ARAB_IMAGE () {                  //destructor
      destroy();  //free memory
		if(thinned != NULL) thinned->destroy();
		if(connCmpPtr_BeforeSeg != NULL) delete []connCmpPtr_BeforeSeg;
		if(connCmpPtr_AfterSeg != NULL) delete []connCmpPtr_AfterSeg;
		if(subwordsPtr != NULL) delete []subwordsPtr;
		if(charactersPtr != NULL) delete []charactersPtr;
		if(inc_x1_codes != NULL) delete []inc_x1_codes;
		if(dec_x2_codes != NULL) delete []dec_x2_codes;
		if(inc_x1_codes_Segmented != NULL) delete []inc_x1_codes_Segmented;
		if(dec_x2_codes_Segmented != NULL) delete []dec_x2_codes_Segmented;
		
		featurePointsLst.clear();
		routeList.clear();//FUAD_30_AUG
		origRouteList.clear();
		segmentationCoordsList.clear();
    }

	IMAGE* getThinnedImage() {	//Returns a pointer to the thinned version if the image.
		if(thinned == NULL)
			makeThinnedImage(false);
		return thinned;
	}

	BYTE getThinnedGreyLevel() {	//The thinnedGreyLevel is not 0(black) when the original text is kept. see makeThinnedImage for more details
		return thinnedGreyLevel;
	}

	PixelWithFeatures_LIST* getFeaturesList() {
		return	&featurePointsLst;
	}

	void findBaseline() {	//This function invokes the old baseline detection function, horizontal projection
		BaseLine = Find_BaseLine(this);
	}


	void writeWithFeatures();
	void makeThinnedImage(bool keepOrigText);
	void findRoutes();
	void findSimpleFeatures();
	void getRoute(ICOORD coords, int dir, Route* routePtr);
	void routeToPolygon(PixelWithDiffs_LIST* pxDers_list, PolygonalEdge_LIST* poly_list, double maxErrorDist);
	void detectLoops();
	void findEdgeFeatures();
	void findSubtleBranchFeatures();
	void splitRoute(Route_IT* route_it_Ptr, PixelWithFeatures PT1);
	void findSegmentationPoints(IMAGE* coloredCmpsImg);
	bool findCutPosition(Route* routePtr, ICOORD* cutPositionPtr);
	void markSegPointsOnImage();
	void markSegPointsOnImage(IMAGE* destImg);
	double getBisectorAngle(ICOORD pt_prev, ICOORD pt,ICOORD pt_next);
	void writeImgWithAllDetails(const char* FNAME);
	void removeSeconderies();
	void makeImagBinary();
	void filterBadFeatures(Route_IT* route_it);//Not used for now
	void copySegmentationMarks(ARAB_IMAGE* source, IMAGE* dest);//Not used for now
	void operator=(ARAB_IMAGE* other);

	void getRoutDiffs(PixelWithDiffs_IT* pxDers_it);
	int getRouteLength(ICOORD PT1, ICOORD PT2, PixelWithDiffs_LIST* pxDers_LIST);
	inline void putPixelThinned(ICOORD coords, BYTE greyLevel);
	inline void putPixelImage(ICOORD coords, BYTE greyLevel);


	void colorConnectedComponents();
	void identifySeconderies();
	void assignSeconderiesSubwords();
	void extractSubwords();
	void segmentToChars(IMAGE* dest);
	void assignSeconderiesLetters();
	void extractLetters();
	void preRecognizeChars(connCmpInf* connCmpPtr, int noOfCmps);
	bool cmpGotSegPoint(BYTE cmpCode);
	void findSegPointsInComponent(BYTE cmpCode, connCmpInf* connCmpPtr, SEG_POINT_IT* segPts_it);
	void copyRoutesList(Route_LIST* source, Route_LIST* dest);
	void copyFeaturesList(PixelWithFeatures_LIST* source, PixelWithFeatures_LIST* dest);

	bool gotSeconderyBelow(connCmpInf* connCmpPtr, int noOfCmps, int x1, int x2, int ymin);



//private:
	connCmpInf*				connCmpPtr_BeforeSeg;
	connCmpInf*				connCmpPtr_AfterSeg;
	subword*				subwordsPtr;
	subword*				charactersPtr;
	BYTE*					inc_x1_codes;
	BYTE*					dec_x2_codes;
	BYTE*					inc_x1_codes_Segmented;
	BYTE*					dec_x2_codes_Segmented;
	int						numOfCmps_BeforeSeg;
	int						numOfCmps_AfterSeg;
	int						numOfSubwords;
	int						numOfCharacters;
	int						numOfCmps_Final;
	int						numOfChars_Final;


	IMAGE*					thinned;
	BYTE					thinnedGreyLevel;
	PixelWithFeatures_LIST	featurePointsLst;
	Route_LIST				routeList;
	Route_LIST				origRouteList;
	SEG_POINT_LIST			segmentationCoordsList;
	int						BaseLine;
};



#endif


